package com.cz.datafetcher.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cz.datafetcher.common.SysError;
import com.cz.datafetcher.dao.FetchDataMapper;
import com.cz.datafetcher.dao.FetchDevicesMapper;
import com.cz.datafetcher.dao.FetchWaysMapper;
import com.cz.datafetcher.entity.FetchData;
import com.cz.datafetcher.entity.FetchDevices;
import com.cz.datafetcher.entity.FetchWays;
import com.cz.datafetcher.entity.PostEntity;
import com.cz.datafetcher.fetcher.IFetcher;
import com.cz.datafetcher.service.FetchDataService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class FetchDataServiceImpl extends ServiceImpl<FetchDataMapper, FetchData> implements FetchDataService {

    @Autowired
    FetchDevicesMapper fetchDevicesMapper;
    @Autowired
    FetchWaysMapper fetchWaysMapper;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    FetchDataMapper fetchDataMapper;

    //获取一个采集设备的数据
    private List<FetchData> Fetch1Device(FetchDevices fetchDevice, Date begin, Date end) {
        // 处理周期问题
        long timeDuration = end.getTime() - begin.getTime();
        long times = timeDuration / (fetchDevice.getPeriod()*1000);
        if(times<1) times=1;
        List<FetchData> r = new ArrayList<>();
        for(Integer i=0;i<times;i++){
            long begintick = begin.getTime() + fetchDevice.getPeriod() * i * 1000;

            Date thisbegin=new Date(begintick+1000);
            Date thisend=new Date(begintick+fetchDevice.getPeriod()*1000);



            //log.info("{} to {}",thisbegin.getTime(),thisend.getTime());
            FetchData fetchData = fetch1Device1PeroidData(fetchDevice, thisbegin, thisend);
            r.add(fetchData);
        }
        return r;
    }

    private FetchData fetch1Device1PeroidData(FetchDevices fetchDevice, Date begin, Date end) {
        BigDecimal oneData = fetchFrom3rd(fetchDevice, begin, end);
        FetchData last = getlast(fetchDevice, begin);
        //System.out.println("最后一条"+last+","+begin+" to "+end);
        //处理期初值
        BigDecimal lastvalue = last == null ? fetchDevice.getBeginValue() : last.getFetchData();
        //处理上一条是异常数据
        if(lastvalue.compareTo(BigDecimal.ZERO)<=0){
            last = getlastBigerthan0(fetchDevice, begin);
            lastvalue = last == null ? fetchDevice.getBeginValue() : last.getFetchData();
        }
        //System.out.println("最后一次数值"+lastvalue);
        //处理异常数据
        BigDecimal growth = oneData.subtract(lastvalue);
        if(growth.compareTo(BigDecimal.ZERO)<0 ){
            growth=BigDecimal.ZERO;
        }
        FetchData r = new FetchData();
        r.setFetchDevicesId(fetchDevice.getId());
        r.setFetchData(oneData);
        r.setLastData(lastvalue);
        r.setFetchBeginTime(begin);
        r.setFetchEndTime(end);
        r.setGrowth(growth);
        r.setCreateTime(new Date());
        save2Data(r);
        return r;
    }

    private void save2Data(FetchData r) {
        QueryWrapper<FetchData> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(FetchData::getFetchDevicesId,r.getFetchDevicesId())
                .eq(FetchData::getFetchBeginTime,r.getFetchBeginTime())
                .eq(FetchData::getFetchEndTime,r.getFetchEndTime())
                .last(" limit 1");
        FetchData entity = this.baseMapper.selectOne(qw);
        if(entity!=null){
            r.setId(entity.getId());
        }
        //log.info("保存采集到的数据：{}",r);
        this.saveOrUpdate(r);
    }

    private FetchData getlastBigerthan0(FetchDevices fetchDevice, Date begin) {
        FetchData last;
        QueryWrapper<FetchData> qw1 = new QueryWrapper<>();
        qw1.lambda()
                .eq(FetchData::getFetchDevicesId, fetchDevice.getId())
                .lt(FetchData::getFetchEndTime, begin)
                .gt(FetchData::getFetchData,0)
                .orderByDesc(FetchData::getFetchEndTime)
                .last(" limit 1");
        last=fetchDataMapper.selectOne(qw1);
        return last;
    }

    private FetchData getlast(FetchDevices fetchDevice, Date begin) {
        QueryWrapper<FetchData> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(FetchData::getFetchDevicesId, fetchDevice.getId())
                .lt(FetchData::getFetchEndTime, begin)
                .orderByDesc(FetchData::getFetchEndTime)
                .last(" limit 1");
        return fetchDataMapper.selectOne(qw);
    }

    //从第三方平台获取数据
    private BigDecimal fetchFrom3rd(FetchDevices fetchDevice, Date begin, Date end) {
        FetchWays fetchWays = fetchWaysMapper.selectById(fetchDevice.getFetchWays());
        IFetcher fetcher = (IFetcher) applicationContext.getBean(fetchWays.getApiClass());
        begin = new Date(begin.getTime() + 1);
        return fetcher.FetchOneData(fetchDevice.getPlatformid(), begin, end);
    }


    @Override
    public HashMap<String, List<FetchData>> Fetch(String fetchDeviceIds, Date begin, Date end, boolean save2db) {
        //log.info("采集{}从{}到{}的数据", fetchDeviceIds,begin.getTime(),end.getTime());
        String[] ids = fetchDeviceIds.split(",");
        List<FetchDevices> fetchDevices = fetchDevicesMapper.selectBatchIds(Arrays.asList(ids));
        //log.info("size {}",fetchDevices.size());
        HashMap<String, List<FetchData>> map = new HashMap<>();
        for (FetchDevices fetchDevice : fetchDevices) {
            if(!fetchDevice.isEnable()) continue;
            Integer fetchWaysId = fetchDevice.getFetchWays();
            FetchWays fetchWays = fetchWaysMapper.selectById(fetchWaysId);
            if(fetchWays==null || StringUtils.isBlank(fetchWays.getApiClass())){
                //不存在的取数方式，或取数方式没有配置数据类（如推送）
                continue;
            }
            List<FetchData> fetchData = Fetch1Device(fetchDevice, begin, end);
            map.put(fetchDevice.getId().toString(), fetchData);
        }
        return map;
    }

    @Override
    public void SavePostValue(PostEntity entity) throws SysError {
        Date begin = entity.getBegin();
        Calendar beginc = Calendar.getInstance();
        beginc.setTime(begin);
        beginc.set(Calendar.MINUTE,0);
        beginc.set(Calendar.SECOND,0);
        beginc.set(Calendar.MILLISECOND,0);
        beginc.add(Calendar.SECOND,1);
        entity.setBegin(beginc.getTime());

        Date end = entity.getEnd();
        Calendar endc = Calendar.getInstance();
        endc.setTime(end);
        endc.set(Calendar.MINUTE,0);
        endc.set(Calendar.SECOND,0);
        endc.set(Calendar.MILLISECOND,0);
        entity.setEnd(endc.getTime());

        FetchData r = new FetchData();
        r.setFetchDevicesId(entity.getDeviceId());
        r.setFetchData(entity.getValue());

        r.setFetchBeginTime(entity.getBegin());
        r.setFetchEndTime(entity.getEnd());
        r.setCreateTime(new Date());
        FetchDevices fetchDevice = fetchDevicesMapper.selectById(entity.getDeviceId());
        if(fetchDevice==null){
            throw new SysError(400,"没有id为"+entity.getDeviceId()+"的采集设备");
        }
        FetchWays fetchWays = fetchWaysMapper.selectById(fetchDevice.getFetchWays());
        if(fetchWays==null || StringUtils.isNotBlank(fetchWays.getApiClass())){
            throw new SysError(401,"该设备不是推送数据设备");
        }
        if(!fetchWays.getPosterKey().equals(entity.getPoster())){
            throw new SysError(402,"推送者密钥不符");
        }
        if(entity.isSumvalue()){
            //是累计量

            FetchData last = getlast(fetchDevice, entity.getBegin());
            //System.out.println("最后一条"+last+","+begin+" to "+end);
            //处理期初值
            BigDecimal lastvalue = last == null ? fetchDevice.getBeginValue() : last.getFetchData();
            //处理上一条是异常数据
            if(lastvalue.compareTo(BigDecimal.ZERO)<=0){
                last = getlastBigerthan0(fetchDevice, entity.getBegin());
                lastvalue = last == null ? fetchDevice.getBeginValue() : last.getFetchData();
            }
            //System.out.println("最后一次数值"+lastvalue);
            //处理异常数据
            BigDecimal growth = entity.getValue().subtract(lastvalue);
            if(growth.compareTo(BigDecimal.ZERO)<0 ){
                growth=BigDecimal.ZERO;
            }
            r.setLastData(lastvalue);
            r.setGrowth(growth);
        }
        else {
            //是增长量
            r.setGrowth(entity.getValue());
        }
        save2Data(r);
    }
}
